from SdlDotNet import *
from System.Drawing import Color, Point
import sys

from kant.pages import *

def parseConfig(text):
    for n, v in [item.strip().split('=', 1) 
                for item in text.split('\n') 
                if not item.startswith('#')]:
        KC.set(n.strip(), v.strip())

def highlightCodePage(title, filename, **kw):
    titles = [ line for line in open(filename, 'r')
        if line.strip().startswith('#=') ]
    tokens = [ l.split(' ', 1)[0][2:].strip() for l in titles]
    tokens.sort()
    print filename, tokens
    if not tokens:
        tokens = ['00']
    print "tokens",tokens
    return [CodeFilePage(title, filename, highlight=t, **kw) for t in tokens]

class Directive:
    def __init__(self, directive, dirname, Max):
        if len(directive) > len(dirname):
            S = directive[len(dirname)]
            self.items = [x for x in directive.strip().split(S)[:Max]]
        else:
            self.items = []
        if len(self.items) < Max:
            self.items += [''] * (Max-len(self.items))
    def __iter__(self):
        return iter(self.items)


def pageParse(page):
    if page.startswith('!'):
        page = page[1:]
        if page.startswith('IMG'):
            typ, imgfile, imgtitle, flags = Directive(page, 'IMG', 4)
            flags = parseFlags(flags)
            kw = { 'nofooter': 'NOFOOTER' in flags, }
            if 'AUTO' in flags:
                pass
#               timer = float(flags.get('AUTO', 0))
#               return AutoImagePage(imgtitle.strip(), imgfile.strip(), 
#                                                        timer=timer, **kw),
            else:
                return ImagePage(imgtitle.strip(), imgfile.strip(), **kw)
        elif page.startswith('CODE'):
            typ, codefile, codetitle, flags = Directive(page, 'CODE', 4) 
            flags = parseFlags(flags)
            print "flags are", flags, 'HILITE' in flags
            kw= {
                    'skiphashbang': 'SKIPHASHBANG' in flags,
                    'nofooter': 'NOFOOTER' in flags,
                }
            if 'HILITE' in flags:
                return highlightCodePage(codetitle, codefile, **kw)
            else:
                return CodeFilePage(codetitle, codefile, **kw)
        elif page.startswith('SPAWN'):
            typ, command, flags = Directive(page, 'SPAWN', 3) 
            return SpawnPage(command)
#            elif 'AUTO' in flags:
#                timer = float(flags.get('AUTO', 0))
#                P(AutoCodeFilePage(codetitle, codefile, timer=timer, **kw))
        elif page.startswith('PY'):
            dirline, commands = page.split('\n', 1)
            typ, title, flags = Directive(dirline, 'PY', 3)
            flags = parseFlags(flags)
            return InterpreterPage(title, commands, flags.get('SYSVER', False))

#      if page.startswith('IMG'):
#            blah, title, filename = page.strip().split('|')
#            return ImagePage(title, filename)
#        if page.startswith('CODE'):
#            blah, title, filename = page.strip().split('|')
#            return CodeFilePage(title, filename)
#        if page.startswith('CONFIG'):
#            dir, config = page.split('\n', 1)
#            parseConfig(config)
    else:
        return TextPage(page.split('\n'))

def parseFlags(flags):
    """ Takes a string of form 'FOO BAR=BAZ BOO' and 
        returns { 'FOO': True, 'BAR': 'BAZ', 'BOO': True }
    """
    # Woo one-liners FTW
    return dict([(f.split('=', 1) + [True])[:2] for f in flags.split()])

class Presentation:
    def __init__(self, pages):
        self._pagelist = []
        self._curPageNumber = None
        for pagetext in pages.split('\n---\n'):
            page = pageParse(pagetext)
            if page: 
                if isinstance(page, list):
                    self._pagelist += page
                else:
                    self._pagelist.append(page)
        Events.MouseButtonDown += self.mouseClick
        Events.KeyboardDown += self.keyPress
        Events.KeyboardUp += self.keyRelease

    def initPages(self):
        for page in self._pagelist:
            page.init()

    def movePage(self, diff=0):
        if self._curPageNumber is None:
            self._curPageNumber = 0
            return
        c = self._curPageNumber + diff
        if c < 0: c = 0
        if c >= len(self._pagelist): c = len(self._pagelist) - 1
        self._curPageNumber = c

    def curPage(self):
        if self._curPageNumber is None:
            return Page()
        return self._pagelist[self._curPageNumber]

    def render(self):
        page = self.curPage()
        Video.Screen.Fill(page.bgcolour)
        if page.render():
            self.nextAction()
        Video.Screen.Flip()

    def setMode(self, fullscreen):
        m = VideoModes.HardwareSurface|VideoModes.DoubleBuffering
        if fullscreen:
            m = m|VideoModes.Fullscreen
        Video.SetVideoMode(KC.screenWidth, KC.screenHeight, 24, m)
                    
    def Run(self):
        self.fullscreen = KC.fullscreen
        self.setMode(self.fullscreen)
        Video.WindowCaption = "IronKant"
        self.initPages()
        Events.Run()

    def nextAction(self, adv=None):
        if adv is None:
            res = self.curPage().next()
            if not res:
                self.movePage(1)
        else:
            self.movePage(adv)
        self.render()

    def prevAction(self, adv=None):
        if adv is None:
            res = self.curPage().prev()
            if not res:
                self.movePage(-1)
        else:
            self.movePage(adv)
        self.render()

    def mouseClick(self, sender, event):
        if event.Button == MouseButton.PrimaryButton:
            self.nextAction()
        elif event.Button == MouseButton.SecondaryButton:
            self.prevAction()
        elif event.Button == MouseButton.WheelDown:
            self.nextAction(5)
        elif event.Button == MouseButton.WheelUp:
            self.prevAction(-5)
        else:
            page = self.curPage()
            if page.mouseClick(sender, event):
                page.render()

    def keyRelease(self, sender, event):
        self.curPage().keyRelease(sender, event)

    def keyPress(self, sender, event):
        if event.Key == Key.Escape:
            sys.exit(0)
        elif event.Key == Key.F1:
            self.fullscreen = not self.fullscreen
            self.setMode(self.fullscreen)
            self.render()
        elif event.Key == Key.UpArrow:
            self.prevAction(-5)
        elif event.Key == Key.DownArrow:
            self.nextAction(5)
        elif event.Key == Key.LeftArrow:
            self.prevAction()
        elif event.Key == Key.RightArrow:
            self.nextAction()
        else:
            page = self.curPage()
            page.keyPress(sender, event)
            Video.Screen.Fill(page.bgcolour)
            page.render()
            Video.Screen.Flip()

